using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace passitumi
{
	/**
	 * This class is responsible for receiving the files as well
	 * as listening for incoming files that other peers are sending.
	 * There needs to be a lot more work done here, most of the code 
	 * is from (http://codetechnic.blogspot.com/2009/02/receiving-large-files-over-tcpip-in-c.html)
	 */
	public class FileListener
	{
		Thread t1;
		int flag = 0;
		string receivedPath = "";
		public delegate void MyDelegate();

		public FileListener(String receivedPath)
		{
			this.receivedPath = receivedPath;
			t1 = new Thread(new ThreadStart(StartListening));
			t1.Start();
		}
		public void quit()
		{
			t1.Abort();
		}

		public class StateObject
		{
			// Client socket.
			public System.Net.Sockets.Socket workSocket = null;

			public const int BufferSize = 8192;
			// Receive buffer.
			public byte[] buffer = new byte[BufferSize];
		}

		public static ManualResetEvent allDone = new ManualResetEvent(false);

		public void StartListening()
		{

			byte[] bytes = new Byte[1024];
			IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 3691);
			System.Net.Sockets.Socket listener = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			try
			{
				listener.Bind(ipEnd);
				listener.Listen(100);
				while (true)
				{
					allDone.Reset();
					listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
					allDone.WaitOne();
				}
			}
			catch (Exception ex)
			{

			}

		}
		public void AcceptCallback(IAsyncResult ar)
		{
			allDone.Set();

			System.Net.Sockets.Socket listener = (System.Net.Sockets.Socket)ar.AsyncState;
			System.Net.Sockets.Socket handler = listener.EndAccept(ar);

			StateObject state = new StateObject();
			state.workSocket = handler;
			handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
				new AsyncCallback(ReadCallback), state);
			flag = 0;
		}

		public void ReadCallback(IAsyncResult ar)
		{

			int fileNameLen = 1;
			String content = String.Empty;
			StateObject state = (StateObject)ar.AsyncState;
			System.Net.Sockets.Socket handler = state.workSocket;
			int bytesRead = handler.EndReceive(ar);
			if (bytesRead > 0)
			{

				if (flag == 0)
				{
					fileNameLen = BitConverter.ToInt32(state.buffer, 0);
					string fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen);
					receivedPath = receivedPath + fileName;
					flag++;
				}
				if (flag >= 1)
				{
					BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append));
					if (flag == 1)
					{
						writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen));
						flag++;
					}
					else
						writer.Write(state.buffer, 0, bytesRead);
					writer.Close();
					handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
					new AsyncCallback(ReadCallback), state);
				}
			}
		}
	}
}
